//
//  MIT License
//  Copyright (c) 2020-2021 Raycast. All rights reserved.
//

import Foundation
import TSCBasic

final class Documentation {
  private let fileSystem = TSCBasic.localFileSystem

  private let path: AbsolutePath

  private let markdownFilename: String
  private let jsonFilename: String

  init(path: AbsolutePath, jsonFilename: String, markdownFilename: String) {
    self.path             = path
    self.jsonFilename     = jsonFilename
    self.markdownFilename = markdownFilename
  }

  func generateDocuments(for data: RaycastData) throws {
    try generateMarkdown(for: data)
    try generateJSON(for: data)
  }
}

// MARK: - Private methods

private extension Documentation {
  func generateMarkdown(for raycastData: RaycastData) throws {
    let documentFilePath = path.appending(
      component: markdownFilename
    )

    guard let data = markdownData(for: raycastData) else {
      return
    }

    try fileSystem.writeFileContents(
      documentFilePath,
      bytes: ByteString(data.uint8Array)
    )
  }

  func generateJSON(for raycastData: RaycastData) throws {
    let documentFilePath = path.appending(
      component: jsonFilename
    )

    let data = try raycastData.toData()

    try fileSystem.writeFileContents(
      documentFilePath,
      bytes: ByteString(data.uint8Array)
    )
  }

  func markdownData(for raycastData: RaycastData) -> Data? {
    let groups = raycastData.groups
    var tableOfContents = String.empty
    var contentString = String.empty

    let sortedGroups = groups.sorted()

    sortedGroups.forEach {
      tableOfContents += $0.markdownDescription
    }

    sortedGroups.forEach { group in
      contentString += .newLine + group.sectionTitle

      contentString += renderMarkdown(for: group)
    }

    let markdown = """
      <!-- AUTO GENERATED FILE. DO NOT EDIT. -->
      \(renderBadges())

      # Raycast Script Commands

      [Raycast](https://raycast.com) lets you control your tools with a few keystrokes
      and Script Commands makes it possible to execute scripts from anywhere on your desktop.
      They are a great way to speed up every-day tasks such as converting data, opening bookmarks
      or triggering dev workflows.

      This repository contains sample commands and documentation to write your own ones.

      ### Categories
      \(tableOfContents)\(contentString)

      ## Community

      This is a shared place and we're always looking for new Script Commands or other ways to improve Raycast.
      If you have anything cool to show, please send us a pull request. If we screwed something up,
      please report a bug. Join our
      [Slack community](https://www.raycast.com/community)
      to brainstorm ideas with like-minded folks.
      """

    guard let contentData = markdown.data(using: .utf8) else {
      return nil
    }

    return contentData
  }

  func renderMarkdown(for group: Group, headline: Bool = false) -> String {
    var contentString = String.empty

    if group.scriptCommands.isEmpty == false {
      if headline {
        contentString += .newLine
        contentString += .newLine + "#### \(group.name)"
      }

      contentString += .newLine
      contentString += .newLine + "| Icon | Title | Description | Author | Args | Templ | Lang |"
      contentString += .newLine + "| :--: | ----- | ----------- | :----: | :--: | :---: | :--: |"

      for scriptCommand in group.scriptCommands.sorted() {
        contentString += scriptCommand.markdownDescription
      }
    }

    if let subGroups = group.subGroups?.sorted() {
      for subGroup in subGroups {
        contentString += renderMarkdown(
          for: subGroup,
          headline: true
        )
      }
    }

    return contentString
  }

  func renderBadges() -> String {
    let logo = ""

    let style      = "for-the-badge"
    let labelColor = "202123"
    let dataURL    = "https:%2F%2Fraw.githubusercontent.com%2Fraycast%2Fscript-commands%2Fmaster%2Fcommands%2Fextensions.json"
    let jsonPath   = "$.totalScriptCommands"

    let badges = """
    <div align="center">
      <a href="https://github.com/raycast/script-commands">
        <img alt="GitHub contributors" src="https://img.shields.io/badge/dynamic/json?style=\(style)&color=\(labelColor)&label=Script%20Commands&query=\(jsonPath)&url=\(dataURL)&logo=\(logo)&labelColor=\(labelColor)">
      </a>
      <a href="https://github.com/raycast/script-commands/graphs/contributors">
        <img alt="GitHub contributors" src="https://img.shields.io/github/stars/raycast?style=\(style)">
      </a>
      <a href="https://github.com/raycast/script-commands/stargazers">
        <img alt="GitHub Org's stars" src="https://img.shields.io/github/contributors/raycast/script-commands?style=\(style)">
      </a>
      <a href="https://twitter.com/raycastapp">
        <img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/raycastapp?style=\(style)">
      </a>
    </div>
    """

    return badges
  }
}
